package com.quanyan.ic.vendingMachine;

import com.alibaba.druid.pool.DruidDataSource;
import com.quanyan.ic.common.spring.SpringUtil;
import com.quanyan.ic.vendingMachine.protocol.server.VmServer;
import com.quanyan.ic.vendingMachine.protocol.server.session.Session;
import com.quanyan.ic.vendingMachine.protocol.server.session.SessionManager;
import com.quanyan.ic.vendingMachine.protocol.server.session.cache.HashMapSessionCache;
import com.quanyan.ic.vendingMachine.protocol.server.session.cache.SessionCache;
import com.quanyan.ic.vendingMachine.protocol.server.session.cache.SessionSerializer;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@SpringBootApplication
@EnableCaching(proxyTargetClass = true)
@MapperScan(basePackages = {"com.quanyan.ic.vendingMachine.mapper"})
@EnableTransactionManagement
@ComponentScan(basePackages = {
        "com.quanyan.ic.*"
})
public class Application {

    public static void main(String[] args) throws InterruptedException {

        SpringApplication
                .run(Application.class, args)
                .addApplicationListener(new ApplicationListener<ContextRefreshedEvent>() {
                    @Override
                    public void onApplicationEvent(ContextRefreshedEvent event) {
                        System.out.println("ContextRefreshed");
                    }
                });    //启动web容器，HTTP 9083 端口

        VmServer vmServer = SpringUtil.getBean(VmServer.class);
        vmServer.start();    //启动tcp服务，TCP 9264 端口
    }

    @Value("${tcp.server.port}")
    private Integer tcpServerPort;

    @Bean(name = "dataSource", destroyMethod = "close", initMethod = "init")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return new DruidDataSource();
    }







    @Bean
    public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/com/quanyan/ic/vendingMachine/mapper/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public <K, V> CacheManager cacheManager(RedisTemplate<K, V> redisTemplate) {
        return new RedisCacheManager(redisTemplate);
    }

    @Bean("sessionRedisTemplate")
    public RedisTemplate<String, Session> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Session> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setValueSerializer(new SessionSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

//	@Bean
//	public SessionCache sessionCache(RedisTemplate<String, Session> sessionRedisTemplate){
//		return new SessionRedisCache(sessionRedisTemplate);
//	}

    @Bean
    public SessionCache sessionCache() {
        return new HashMapSessionCache();
    }

    //客户端session缓存管理器
    @Bean
    public SessionManager sessionManager(SessionCache sessionCache) {
        return new SessionManager(sessionCache);
    }

    @Bean
    public VmServer vmServer(SessionManager sessionManager) {
        VmServer vmServer = new VmServer();
        vmServer.setSessionManager(sessionManager);
        vmServer.setPort(tcpServerPort);
        return vmServer;
    }
}
